package com.example.basic.web.service.zoneDepot.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.basic.base.impl.BaseEntityServiceImpl;
import com.example.basic.exception.ServiceException;
import com.example.basic.utils.IdUtils;
import com.example.basic.web.enums.DataCodeEnum;
import com.example.basic.web.enums.EnableTypeEnum;
import com.example.basic.web.mapper.zoneDepot.ZoneDepotMapper;
import com.example.basic.web.model.pharmStock.PharmStock;
import com.example.basic.web.model.pharmZone.PharmZone;
import com.example.basic.web.model.zoneDepot.ZoneDepot;
import com.example.basic.web.request.DepotQueryRequest;
import com.example.basic.web.request.ZoneDepotRequest;
import com.example.basic.web.response.report.StockCountResponse;
import com.example.basic.web.response.report.StockSumReportResponse;
import com.example.basic.web.service.dataCode.DataCodeService;
import com.example.basic.web.service.pharmStock.PharmStockService;
import com.example.basic.web.service.pharmZone.PharmZoneService;
import com.example.basic.web.service.zoneDepot.ZoneDepotService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.example.basic.utils.CheckUtil.notNull;


@Service
public class ZoneDepotServiceImpl extends BaseEntityServiceImpl<ZoneDepotMapper, ZoneDepot> implements ZoneDepotService {

    @Resource
    private ZoneDepotMapper zoneDepotMapper;

    @Resource
    private DataCodeService dataCodeService;

    @Resource
    private PharmZoneService pharmZoneService;

    @Resource
    private PharmStockService pharmStockService;


    /**
     * 保存库位信息  zzl
     * @param zoneDepotRequest 模型
     * @return
     */
    @Override
    public Boolean saveDepot(ZoneDepotRequest zoneDepotRequest) {

        //获取分区信息
        PharmZone pharmZone = pharmZoneService.detail(zoneDepotRequest.getZoneCode());

        //判断是否维护库位
        List<ZoneDepot> zoneDepots = this.queryByZone(zoneDepotRequest.getZoneCode());
        if(zoneDepots.size() > 0){
            throw new ServiceException("已维护库位");
        }

        //如果有停用库位，会有异常产生，所以先清空当前分区库位
        zoneDepotMapper.removeByZoneCde(zoneDepotRequest.getZoneCode());

        if(pharmZone == null){
            throw new ServiceException("分区编码无效");
        }
        if(pharmZone.getColumnNum() < zoneDepotRequest.getColumnNum()){
            throw new ServiceException("列数无效");
        }
        if(pharmZone.getLayerNum() < zoneDepotRequest.getLayerNum()){
            throw new ServiceException("层数无效");
        }
        if(pharmZone.getRowsNum() < zoneDepotRequest.getRowsNum()){
            throw new ServiceException("行数无效");
        }

        List<ZoneDepot> saveList = new ArrayList<>();

        //根据层数，行数，列数批量生成库位
        for (Integer layerNum = 1; layerNum <= zoneDepotRequest.getLayerNum(); layerNum++) {
            for (Integer rowsNum = 1; rowsNum <= zoneDepotRequest.getRowsNum(); rowsNum++) {
                for (Integer columnNum = 1; columnNum <= zoneDepotRequest.getColumnNum(); columnNum++) {
                    ZoneDepot zoneDepot = new ZoneDepot();
                    zoneDepot.setPharmCode(zoneDepotRequest.getPharmCode());
                    zoneDepot.setColumnNum(columnNum);
                    zoneDepot.setLayerNum(layerNum);
                    zoneDepot.setRowsNum(rowsNum);
                    zoneDepot.setZoneCode(zoneDepotRequest.getZoneCode());
                    zoneDepot.setId(IdUtils.fastUUID());
                    preCreate(zoneDepot);

                    saveList.add(zoneDepot);
                }
            }
        }

        //生成库位编码
        List<String> depotCodes = dataCodeService.generateDataCodeNoList(DataCodeEnum.DEPOT_CODE.getType(), saveList.size());

        for (int i = 0; i < saveList.size(); i++) {
            saveList.get(i).setDepotCode(depotCodes.get(i));
        }

        return saveBatch(saveList);
    }

    /**
     * 更新库位信息
     * @param zoneDepot
     * @return
     */
    @Override
    public ZoneDepot modify(ZoneDepot zoneDepot) {
        notNull(zoneDepot.getDepotCode(),"库位编码不能为空");
        notNull(zoneDepot.getPharmCode(),"仓库编码不能为空");
        notNull(zoneDepot.getZoneCode(),"分区编码不能为空");
        notNull(zoneDepot.getRowsNum(),"行数不能为空");
        notNull(zoneDepot.getLayerNum(),"层数不能为空");
        notNull(zoneDepot.getColumnNum(),"列数不能为空");

        LambdaQueryWrapper<ZoneDepot> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ZoneDepot::getPharmCode,zoneDepot.getPharmCode());
        lqw.eq(ZoneDepot::getZoneCode,zoneDepot.getZoneCode());
        lqw.eq(ZoneDepot::getLayerNum,zoneDepot.getLayerNum());
        lqw.eq(ZoneDepot::getColumnNum,zoneDepot.getColumnNum());
        lqw.eq(ZoneDepot::getRowsNum,zoneDepot.getRowsNum());
        lqw.ne(ZoneDepot::getDepotCode,zoneDepot.getDepotCode());
        ZoneDepot localZoneDepot = this.mapper.selectOne(lqw);

        if(localZoneDepot != null){
            throw new ServiceException("当前库位已存在");
        }

        //判断点位是否已维护
        LambdaQueryWrapper<ZoneDepot> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ZoneDepot::getDepotPoint, zoneDepot.getDepotPoint());
        queryWrapper.ne(ZoneDepot::getId, zoneDepot.getId());
        List<ZoneDepot> zoneDepots = this.mapper.selectList(queryWrapper);
        if(!zoneDepots.isEmpty()){
            throw new ServiceException("库位点位已存在");
        }

        preUpdate(zoneDepot);

        if(this.updateById(zoneDepot) > 0){
            return detail(zoneDepot.getDepotCode());
        }
        throw new ServiceException("更新失败");
    }

    /**
     * 详情
     * @param depotCode 库位编码
     * @return
     */
    @Override
    public ZoneDepot detail(String depotCode) {
        notNull(depotCode, "库位编码不能为空");
        return zoneDepotMapper.detail(depotCode);
    }

    /**
     * 删除
     * @param depotCode 库位编码
     * @return
     */
    @Override
    public int delete(String depotCode) {
        notNull(depotCode,"库位编码不能为空");

        ZoneDepot zoneDepot = detail(depotCode);
        if(zoneDepot == null){
            throw new ServiceException("未查询到当前数据");
        }

        //判断库位是否使用
        PharmStock pharmStock = pharmStockService.judgeStock(zoneDepot.getPharmCode(), zoneDepot.getZoneCode(), zoneDepot.getDepotCode());
        if(pharmStock != null ){
            throw new ServiceException("库位使用中，不允许操作");
        }

        return this.mapper.deleteById(zoneDepot.getId());
    }

    /**
     * 启用/禁用
     * @param depotCode 库位编码
     * @return
     */
    @Override
    public int enableOrDisable(String depotCode) {
        notNull(depotCode,"库位编码不能为空");

        ZoneDepot zoneDepot = detail(depotCode);

        if(zoneDepot == null){
            throw new ServiceException("未查询到当前数据");
        }

        //判断库位是否使用
        PharmStock pharmStock = pharmStockService.judgeStock(zoneDepot.getPharmCode(), zoneDepot.getZoneCode(), zoneDepot.getDepotCode());
        if(pharmStock != null ){
            throw new ServiceException("库位使用中，不允许操作");
        }

        //停用启用
        if(zoneDepot.getEnableFlag().equals(EnableTypeEnum.ON.getType())){
            zoneDepot.setEnableFlag(EnableTypeEnum.OFF.getType());
        }else {
            zoneDepot.setEnableFlag(EnableTypeEnum.ON.getType());
        }

        preUpdate(zoneDepot);

        return this.mapper.updateById(zoneDepot);
    }

    /**
     * 通道列表
     *
     * @param queryPage   分页
     * @param searchParam 模糊搜索(拼音码,五笔码,名称,编码)
     * @param isAll       是否查询全部 0-否，1-是
     * @param zoneCode    分区编码
     * @param pharmCode 仓库编码
     * @return
     */
    @Override
    public IPage<ZoneDepot> queryList(Page<ZoneDepot> queryPage, String searchParam, String isAll, String zoneCode, String pharmCode) {
        return zoneDepotMapper.queryList(queryPage,searchParam,isAll,zoneCode,pharmCode);
    }

    /**
     * 查询分区下在用通道
     * @param zoneCode 分区编码
     * @return
     */
    @Override
    public List<ZoneDepot> queryByZone(String zoneCode) {
        notNull(zoneCode,"分区编码不能为空");

        LambdaQueryWrapper<ZoneDepot> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ZoneDepot::getZoneCode,zoneCode);
        lqw.eq(ZoneDepot::getEnableFlag,EnableTypeEnum.ON.getType());

        return this.mapper.selectList(lqw);
    }

    /**
     * 库位信息查询
     * @param queryPage 分页
     * @param depotQueryRequest
     * @return
     */
    @Override
    public IPage<StockCountResponse> queryDepotInfo(Page<StockCountResponse> queryPage, DepotQueryRequest depotQueryRequest) {
        return this.mapper.queryDepotInfo(queryPage,depotQueryRequest);
    }

    /**
     * 库位信息统计
     * @param depotQueryRequest
     * @return
     */
    @Override
    public Map depotCount(DepotQueryRequest depotQueryRequest) {
        return this.mapper.depotCount(depotQueryRequest);
    }

    /**
     * 库存汇总查询
     * @param pharmCode 仓库编码
     * @param zoneCode 分区编码
     * @return
     */
    @Override
    public List<StockSumReportResponse> stockSumReport(String pharmCode, String zoneCode) {
        return this.mapper.stockSumReport(pharmCode,zoneCode);
    }

    /**
     * 空闲库位列表
     * @param pharmCode 仓库编码
     * @param zoneCode 分区编码
     * @return
     */
    @Override
    public List<ZoneDepot> freeDepotList(String pharmCode, String zoneCode) {
        notNull(pharmCode,"仓库编码不能为空");
        notNull(zoneCode,"分区编码不能为空");
        return this.mapper.freeDepotList(pharmCode,zoneCode);
    }

    /**
     * 获取库位位置
     * @param depotCode 库位编码
     * @return
     */
    @Override
    public String getDepotAddress(String depotCode) {
        notNull(depotCode,"库位编码不能为空");
        return this.mapper.getDepotAddress(depotCode);
    }

    /**
     * 库位统计对比情况
     * @return
     */
    @Override
    public List<Map> homeDepotCount(String pharmCode) {
        return this.mapper.homeDepotCount(pharmCode);
    }

    /**
     * 删除库区库位信息
     * @param zoneCode 库区编码
     * @return
     */
    @Override
    public Boolean removeByZone(String zoneCode) {
        notNull(zoneCode,"分区编码不能为空");

        LambdaQueryWrapper<ZoneDepot> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ZoneDepot::getZoneCode,zoneCode);
        this.mapper.delete(lqw);
        return true;
    }

    /**
     * 更新库位为占用
     * @param depotList
     * @return
     */
    @Override
    public Boolean useDepot(List<String> depotList,String isUse) {
        notNull(depotList,"库位编码集合不能为空");

        UpdateWrapper<ZoneDepot> updateWrapper = new UpdateWrapper();
        updateWrapper.in(ZoneDepot.depot_code,depotList);
        updateWrapper.set(ZoneDepot.is_use, isUse);
        this.mapper.update(null, updateWrapper);

        return true;
    }
}
